﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Collections.Specialized;

namespace System.Web
{
    public class CookieAwareWebClient : WebClient
    {
        public CookieContainer CookieContainer { get; set; }
        public string UserAgent { get; set; }
        public CookieAwareWebClient()
        {
            CookieContainer = new CookieContainer();
        }
        public CookieAwareWebClient(CookieContainer cookieContainer)
        {
            CookieContainer = cookieContainer;
        }
        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            RefreshUserAgent();
            if (request is HttpWebRequest && CookieContainer != null)
            {
                HttpWebRequest r = request as HttpWebRequest;
                r.UserAgent = UserAgent;
                r.CookieContainer = this.CookieContainer;
                r.AllowAutoRedirect = true;
                r.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 
            }
            return request;
        }
        protected override WebResponse GetWebResponse(WebRequest request)
        {
            var r = base.GetWebResponse(request);
            if (r is HttpWebResponse && CookieContainer != null)
                this.CookieContainer.Add((r as HttpWebResponse).Cookies);
            return r;
        }
        public string PostData(string uriString, string postString, string postStringEncoding, string dataEncoding, out string msg)
        {
            try
            {
                // 将 Post 字符串转换成字节数组
                byte[] postData = Encoding.GetEncoding(postStringEncoding).GetBytes(postString);
                this.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                // 上传数据，返回页面的字节数组
                byte[] responseData = this.UploadData(uriString, "POST", postData);
                // 将返回的将字节数组转换成字符串(HTML);
                string srcString = Encoding.GetEncoding(dataEncoding).GetString(responseData);
                srcString = srcString.Replace("\t", "");
                srcString = srcString.Replace("\r", "");
                srcString = srcString.Replace("\n", "");
                msg = string.Empty;
                return srcString;
            }
            catch (WebException we)
            {
                msg = we.Message;
                return string.Empty;
            }
        }

        private void RefreshUserAgent()
        {
            List<string> userAgents = new List<string>();
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.5; AOLBuild 4337.43; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.34; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)");
            userAgents.Add("Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8");
            userAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2a1pre) Gecko/20090402 Firefox/3.6a1pre (.NET CLR 3.5.30729)");
            userAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 GTB5 (.NET CLR 3.5.30729)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727; MAXTHON 2.0)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)");
            userAgents.Add("Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)");
            userAgents.Add("Opera/9.70 (Linux i686 ; U; zh-cn) Presto/2.2.0");
            userAgents.Add("Opera 9.7 (Windows NT 5.2; U; en)");
            userAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.8pre) Gecko/20070928 Firefox/2.0.0.7 Navigator/9.0RC1");
            userAgents.Add("Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.7pre) Gecko/20070815 Firefox/2.0.0.6 Navigator/9.0b3");
            userAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8");
            userAgents.Add("Mozilla/5.0 (Windows; U; Windows NT 6.0; ru-RU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16");
            userAgents.Add("Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1");
            Random r = new Random();
            this.UserAgent = userAgents[r.Next(0, userAgents.Count)];
            userAgents = null;
        }
    }

    public class ZRequest
    {
        public static string GetIP(HttpRequest request)
        {
            string result = String.Empty;

            result = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (result != null && result != String.Empty)
            {
                //可能有代理 
                if (result.IndexOf(".") == -1)    //没有“.”肯定是非IPv4格式 
                    result = null;
                else
                {
                    if (result.IndexOf(",") != -1)
                    {
                        //有“,”，估计多个代理。取第一个不是内网的IP。 
                        result = result.Replace(" ", "").Replace("'", "");
                        string[] temparyip = result.Split(",;".ToCharArray());
                        for (int i = 0; i < temparyip.Length; i++)
                        {
                            if (IsIPAddress(temparyip[i])
                                && temparyip[i].Substring(0, 3) != "10."
                                && temparyip[i].Substring(0, 7) != "192.168"
                                && temparyip[i].Substring(0, 7) != "172.16.")
                            {
                                return temparyip[i];    //找到不是内网的地址 
                            }
                        }
                    }
                    else if (IsIPAddress(result)) //代理即是IP格式 
                        return result;
                    else
                        result = null;    //代理中的内容 非IP，取IP 
                }

            }
            string IpAddress = (request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty) ? request.ServerVariables["HTTP_X_FORWARDED_FOR"] : request.ServerVariables["REMOTE_ADDR"];
            if (null == result || result == String.Empty)
                result = request.ServerVariables["REMOTE_ADDR"];

            if (result == null || result == String.Empty)
                result = request.UserHostAddress;
            return (result.Split(",".ToCharArray()))[0];
        }
        public static string GetIP()
        {
            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
                return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
            else
                return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
        }
        /// <summary> 
        /// 取得客户端真实IP。如果有代理则取第一个非内网地址 
        /// </summary> 
        public static string IPAddress
        {
            get
            {
                string result = String.Empty;

                result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (result != null && result != String.Empty)
                {
                    //可能有代理 
                    if (result.IndexOf(".") == -1)    //没有“.”肯定是非IPv4格式 
                        result = null;
                    else
                    {
                        if (result.IndexOf(",") != -1)
                        {
                            //有“,”，估计多个代理。取第一个不是内网的IP。 
                            result = result.Replace(" ", "").Replace("'", "");
                            string[] temparyip = result.Split(",;".ToCharArray());
                            for (int i = 0; i < temparyip.Length; i++)
                            {
                                if (IsIPAddress(temparyip[i])
                                    && temparyip[i].Substring(0, 3) != "10."
                                    && temparyip[i].Substring(0, 7) != "192.168"
                                    && temparyip[i].Substring(0, 7) != "172.16.")
                                {
                                    return temparyip[i];    //找到不是内网的地址 
                                }
                            }
                        }
                        else if (IsIPAddress(result)) //代理即是IP格式 
                            return result;
                        else
                            result = null;    //代理中的内容 非IP，取IP 
                    }

                }

                string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty) ? HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];



                if (null == result || result == String.Empty)
                    result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

                if (result == null || result == String.Empty)
                    result = HttpContext.Current.Request.UserHostAddress;

                return result;
            }
        }
        public static string IP
        {
            get
            {
                return (IPAddress.Split(",".ToCharArray()))[0];
            }
        }
        #region bool IsIPAddress(str1) 判断是否是IP格式
        /**/
        /// <summary>
        /// 判断是否是IP地址格式 0.0.0.0
        /// </summary>
        /// <param name="str1">待判断的IP地址</param>
        /// <returns>true or false</returns>
        private static bool IsIPAddress(string str1)
        {
            if (str1 == null || str1 == string.Empty || str1.Length < 7 || str1.Length > 15) return false;
            string regformat = @"^/d{1,3}[/.]/d{1,3}[/.]/d{1,3}[/.]/d{1,3}$";
            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);
            return regex.IsMatch(str1);
        }

        #endregion
        private static HttpWebRequest GetRequest(string url, string reference, string cookie)
        {
            try
            {
                var uri = new Uri(url);
                var req = (HttpWebRequest)WebRequest.Create(uri);
                req.Accept =
                    "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/x-shockwave-flash, application/vnd.ms-powerpoint, */*";
                req.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-cn");
                if (reference != "")
                {
                    req.Referer = reference;
                }
                else
                {
                    req.Referer = "http://" + uri.Host;
                }
                req.Headers.Add("UA-CPU:x86");
                req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1;)";
                req.KeepAlive = true;
                if (cookie != "")
                {
                    req.Headers.Add(HttpRequestHeader.Cookie, cookie);
                }
                req.Timeout = 10000;
                return req;
            }
            catch
            {
                return null;
            }
        }
        private static byte[] HttpDecompress(HttpWebResponse resp)
        {
            var offset = 0;
            byte[] deBuffer;
            if (resp == null)
                return null;
            Stream s = null;
            try
            {
                s = resp.GetResponseStream();
                var zipBuffer = new byte[1024 * 1024];
                var bytesRead = 0;
                while (true)
                {
                    if (s != null) bytesRead = s.Read(zipBuffer, offset, zipBuffer.Length - offset);
                    if (bytesRead <= 0)
                        break;
                    offset += bytesRead;
                }
                if (resp.ContentEncoding == "gzip")
                {
                    var ms = new MemoryStream(zipBuffer, 0, offset, true);
                    var zipStream = new GZipStream(ms, CompressionMode.Decompress, true);
                    ms.Seek(0, SeekOrigin.Begin);
                    deBuffer = new byte[1024 * 1024];
                    offset = 0;
                    while (true)
                    {
                        bytesRead = zipStream.Read(deBuffer, offset, 1024);
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        offset += bytesRead;
                    }
                    zipStream.Close();
                }
                else
                {
                    deBuffer = zipBuffer;
                }
                if (s != null) s.Close();
                resp.Close();
            }
            catch
            {
                if (s != null)
                    s.Close();
                return null;
            }
            if (offset > 0)
            {
                var ms = new MemoryStream(deBuffer, 0, offset);
                deBuffer = ms.ToArray();
                ms.Close();
                return deBuffer;
            }
            return null;
        }
        public static string GetWebSiteHtml(string website, string pageUrl, string encode)
        {
            string content = "";
            string sourceURL = ZConfig.ReadAppSettings("SourceURL");
            string sourceAnalyticsURL = ZConfig.ReadAppSettings("SourceAnalyticsURL");
            string targetAnalyticsURL = ZConfig.ReadAppSettings("TargetAnalyticsURL");
            content = GetHtml(sourceURL + pageUrl, encode);
            content = content.Replace(sourceURL, website);
            content = content.Replace(sourceAnalyticsURL, targetAnalyticsURL);

            return content;
        }
        public static string GetHtml(string url, string encode)
        {
            string content;
            try
            {
                //Thread.Sleep(500);
                var resq = GetRequest(url, "", "");
                var resp = (HttpWebResponse)resq.GetResponse();
                var ht = resp.GetResponseHeader("Content-Type");
                var buffer = HttpDecompress(resp);
                try
                {
                    content = Encoding.GetEncoding(encode).GetString(buffer);
                }
                catch (ArgumentException)
                {
                    content = Encoding.GetEncoding("gb2312").GetString(buffer);
                }
                finally
                {
                   
                }
            }
            catch (Exception)
            {
                content = "";
            }
            return content;
        }
        public static string NoHTML(string htmlString)
        {

            //删除脚本 &amp;sect; 
            htmlString = htmlString.Replace("&sect;", "");
            htmlString = htmlString.Replace("&mdash;", "-");
            htmlString = htmlString.Replace("&middot;", ".");
            htmlString = Regex.Replace(htmlString, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            //删除HTML 
            htmlString = Regex.Replace(htmlString, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"-->", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"<!--.*", "", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            // Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase); 
            htmlString = Regex.Replace(htmlString, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            htmlString = Regex.Replace(htmlString, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
          //  htmlString = Regex.Replace(htmlString, @"&#(\d+);", "", RegexOptions.IgnoreCase);
            htmlString.Replace("<", ""); htmlString.Replace(">", "");
            htmlString.Replace("\r\n", "");
            htmlString = htmlString.Trim();
            return htmlString;

        }
        public static string RequestHTML(string url, string method, NameValueCollection postVars, CookieContainer cc, Encoding encode)
        {
            string result = "";
            try
            {
                CookieAwareWebClient webClient = new CookieAwareWebClient(cc);
                byte[] byRemoteInfo = webClient.UploadValues(url, method, postVars);
                result = encode.GetString(byRemoteInfo);
               // string msg;
              //  string s = webClient.PostData(url, postVars.ToString(), "utf-8", "gb2312", out msg);
            }
            catch
            {
                result = "";
            }

            return result;
        }
       
    }
}
